home *** CD-ROM | disk | FTP | other *** search
/ ADA Programming Guide / ADA Programming Guide.iso / ada_gnu / adainc / a-strbou.adb < prev    next >
Text File  |  1996-01-30  |  50KB  |  1,604 lines

  1. ------------------------------------------------------------------------------
  2. --                                                                          --
  3. --                         GNAT RUNTIME COMPONENTS                          --
  4. --                                                                          --
  5. --                  A D A . S T R I N G S . B O U N D E D                   --
  6. --                                                                          --
  7. --                                 B o d y                                  --
  8. --                                                                          --
  9. --                            $Revision: 1.10 $                             --
  10. --                                                                          --
  11. --           Copyright (c) 1992,1993,1994 NYU, All Rights Reserved          --
  12. --                                                                          --
  13. -- The GNAT library is free software; you can redistribute it and/or modify --
  14. -- it under terms of the GNU Library General Public License as published by --
  15. -- the Free Software  Foundation; either version 2, or (at your option) any --
  16. -- later version.  The GNAT library is distributed in the hope that it will --
  17. -- be useful, but WITHOUT ANY WARRANTY;  without even  the implied warranty --
  18. -- of MERCHANTABILITY  or  FITNESS FOR  A PARTICULAR PURPOSE.  See the  GNU --
  19. -- Library  General  Public  License for  more  details.  You  should  have --
  20. -- received  a copy of the GNU  Library  General Public License  along with --
  21. -- the GNAT library;  see the file  COPYING.LIB.  If not, write to the Free --
  22. -- Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.        --
  23. --                                                                          --
  24. ------------------------------------------------------------------------------
  25.  
  26. --  Note: This code is derived from the ADAR.CSH public domain Ada 83
  27. --  versions of the Appendix C string handling packages. Major changes
  28. --  have been made from this starting point. Notably, all use of functions
  29. --  returning strings, and of string concatenation in particular, have been
  30. --  avoided, to make absolutely sure that the heap is not used. The data
  31. --  structure has been simplified to avoid the embedded variant record,
  32. --  which makes it much easier to modify the data of a bounded string
  33. --  in place. Also all dependence on Ada.Strings.Fixed has been removed.
  34.  
  35. with Ada.Strings.Maps;   use Ada.Strings.Maps;
  36. with Ada.Strings.Search;
  37.  
  38. package body Ada.Strings.Bounded is
  39.  
  40.    package body Generic_Bounded_Length is
  41.  
  42.       ---------
  43.       -- "=" --
  44.       ---------
  45.  
  46.       function "=" (Left, Right : in Bounded_String) return Boolean is
  47.       begin
  48.          return Left.Length = Right.Length
  49.            and then Left.Data (1 .. Left.Length) =
  50.                     Right.Data (1 .. Right.Length);
  51.       end "=";
  52.  
  53.       function "="  (Left : in Bounded_String; Right : in String)
  54.          return Boolean is
  55.       begin
  56.          return Left.Length = Right'Length
  57.            and then Left.Data (1 .. Left.Length) = Right (1 .. Right'Length);
  58.       end "=";
  59.  
  60.       function "="  (Left : in String; Right : in Bounded_String)
  61.          return Boolean is
  62.       begin
  63.          return Left'Length = Right.Length
  64.            and then Left (1 .. Left'Length) = Right.Data (1 .. Right.Length);
  65.       end "=";
  66.  
  67.       ---------
  68.       -- "<" --
  69.       ---------
  70.  
  71.       function "<" (Left, Right : in Bounded_String) return Boolean is
  72.       begin
  73.          return Left.Data (1 .. Left.Length) < Right.Data (1 .. Right.Length);
  74.       end "<";
  75.  
  76.       function "<"  (Left : in Bounded_String; Right : in String)
  77.          return Boolean is
  78.       begin
  79.          return Left.Data (1 .. Left.Length) < Right (1 .. Right'Length);
  80.       end "<";
  81.  
  82.       function "<"  (Left : in String; Right : in Bounded_String)
  83.          return Boolean is
  84.       begin
  85.          return Left (1 .. Left'Length) < Right.Data (1 .. Right.Length);
  86.       end "<";
  87.  
  88.       ----------
  89.       -- "<=" --
  90.       ----------
  91.  
  92.       function "<=" (Left, Right : in Bounded_String) return Boolean is
  93.       begin
  94.          return Left.Data (1 .. Left.Length) <= Right.Data (1 .. Right.Length);
  95.       end "<=";
  96.  
  97.       function "<="  (Left : in Bounded_String; Right : in String)
  98.          return Boolean is
  99.       begin
  100.          return Left.Data (1 .. Left.Length) <= Right (1 .. Right'Length);
  101.       end "<=";
  102.  
  103.       function "<="  (Left : in String; Right : in Bounded_String)
  104.          return Boolean is
  105.       begin
  106.          return Left (1 .. Left'Length) <= Right.Data (1 .. Right.Length);
  107.       end "<=";
  108.  
  109.       ---------
  110.       -- ">" --
  111.       ---------
  112.  
  113.       function ">" (Left, Right : in Bounded_String) return Boolean is
  114.       begin
  115.          return Left.Data (1 .. Left.Length) > Right.Data (1 .. Right.Length);
  116.       end ">";
  117.  
  118.       function ">"  (Left : in Bounded_String; Right : in String)
  119.          return Boolean is
  120.       begin
  121.          return Left.Data (1 .. Left.Length) > Right (1 .. Right'Length);
  122.       end ">";
  123.  
  124.       function ">"  (Left : in String; Right : in Bounded_String)
  125.          return Boolean is
  126.       begin
  127.          return Left (1 .. Left'Length) > Right.Data (1 .. Right.Length);
  128.       end ">";
  129.  
  130.       ----------
  131.       -- ">=" --
  132.       ----------
  133.  
  134.       function ">=" (Left, Right : in Bounded_String) return Boolean is
  135.       begin
  136.          return Left.Data (1 .. Left.Length) >= Right.Data (1 .. Right.Length);
  137.       end ">=";
  138.  
  139.       function ">="  (Left : in Bounded_String; Right : in String)
  140.          return Boolean is
  141.       begin
  142.          return Left.Data (1 .. Left.Length) >= Right (1 .. Right'Length);
  143.       end ">=";
  144.  
  145.       function ">="  (Left : in String; Right : in Bounded_String)
  146.          return Boolean is
  147.       begin
  148.          return Left (1 .. Left'Length) >= Right.Data (1 .. Right.Length);
  149.       end ">=";
  150.  
  151.       ---------
  152.       -- "*" --
  153.       ---------
  154.  
  155.       function "*"
  156.         (Left  : in Natural;
  157.          Right : in Character)
  158.          return  Bounded_String
  159.       is
  160.       begin
  161.          return Replicate (Left, Right, Strings.Error);
  162.       end "*";
  163.  
  164.       function "*"
  165.         (Left  : in Natural;
  166.          Right : in String)
  167.          return  Bounded_String
  168.       is
  169.       begin
  170.          return Replicate (Left, Right, Strings.Error);
  171.       end "*";
  172.  
  173.       function "*"
  174.         (Left  : in Natural;
  175.          Right : in Bounded_String)
  176.          return  Bounded_String
  177.       is
  178.       begin
  179.          return Replicate (Left, Right, Strings.Error);
  180.       end "*";
  181.  
  182.       ---------
  183.       -- "&" --
  184.       ---------
  185.  
  186.       function "&" (Left, Right : in Bounded_String)
  187.          return Bounded_String is
  188.       begin
  189.          return Append (Left, Right, Drop => Strings.Error);
  190.       end "&";
  191.  
  192.       function "&" (Left : in Bounded_String; Right : in String)
  193.          return Bounded_String is
  194.       begin
  195.          return Append (Left, Right, Drop => Strings.Error);
  196.       end "&";
  197.  
  198.       function "&" (Left : in String; Right : in Bounded_String)
  199.          return Bounded_String is
  200.       begin
  201.          return Append (Left, Right, Drop => Strings.Error);
  202.       end "&";
  203.  
  204.       function "&" (Left : in Bounded_String; Right : in Character)
  205.          return Bounded_String is
  206.       begin
  207.          return Append (Left, Right, Drop => Strings.Error);
  208.       end "&";
  209.  
  210.       function "&" (Left : in Character; Right : in Bounded_String)
  211.          return Bounded_String is
  212.       begin
  213.          return Append (Left, Right, Drop => Strings.Error);
  214.       end "&";
  215.  
  216.       ------------
  217.       -- Append --
  218.       ------------
  219.  
  220.       --  Case of Bounded_String and Bounded_String
  221.  
  222.       function Append
  223.         (Left, Right : in Bounded_String;
  224.          Drop        : in Strings.Truncation  := Strings.Error)
  225.          return        Bounded_String
  226.       is
  227.          Result : Bounded_String;
  228.          Llen   : constant Length_Range := Left.Length;
  229.          Rlen   : constant Length_Range := Right.Length;
  230.  
  231.       begin
  232.          if Llen + Rlen <= Max_Length then
  233.             Result.Length := Llen + Rlen;
  234.             Result.Data (1 .. Llen) := Left.Data;
  235.             Result.Data (Llen + 1 .. Llen + Rlen) := Right.Data;
  236.  
  237.          else
  238.             Result.Length := Max_Length;
  239.  
  240.             case Drop is
  241.                when Strings.Right =>
  242.                   if Rlen >= Max_Length then
  243.                      Result.Data (1 .. Max_Length) :=
  244.                        Left.Data (1 .. Max_Length);
  245.  
  246.                   else
  247.                      Result.Data (1 .. Llen) := Left.Data;
  248.                      Result.Data (Llen + 1 .. Max_Length) :=
  249.                        Right.Data (1 .. Max_Length - Llen);
  250.                   end if;
  251.  
  252.                when Strings.Left =>
  253.                   if Rlen >= Max_Length then
  254.                      Result.Data (1 .. Max_Length) :=
  255.                        Right.Data (Rlen - (Max_Length - 1) .. Rlen);
  256.  
  257.                   else
  258.                      Result.Data (1 .. Max_Length - Rlen) :=
  259.                        Left.Data (Llen - (Max_Length - Rlen + 1) .. Llen);
  260.                      Result.Data (Max_Length - Rlen + 1 .. Max_Length) :=
  261.                        Right.Data;
  262.                   end if;
  263.  
  264.                when Strings.Error =>
  265.                   raise Strings.Length_Error;
  266.             end case;
  267.          end if;
  268.  
  269.          return Result;
  270.       end Append;
  271.  
  272.       procedure Append
  273.         (Source   : in out Bounded_String;
  274.          New_Item : in Bounded_String;
  275.          Drop     : in Truncation  := Error)
  276.       is
  277.          Llen   : constant Length_Range := Source.Length;
  278.          Rlen   : constant Length_Range := New_Item.Length;
  279.  
  280.       begin
  281.          if Llen + Rlen <= Max_Length then
  282.             Source.Length := Llen + Rlen;
  283.             Source.Data (Llen + 1 .. Llen + Rlen) := New_Item.Data;
  284.  
  285.          else
  286.             Source.Length := Max_Length;
  287.  
  288.             case Drop is
  289.                when Strings.Right =>
  290.                   if Rlen < Max_Length then
  291.                      Source.Data (Llen + 1 .. Max_Length) :=
  292.                        New_Item.Data (1 .. Max_Length - Llen);
  293.                   end if;
  294.  
  295.                when Strings.Left =>
  296.                   if Rlen >= Max_Length then
  297.                      Source.Data (1 .. Max_Length) :=
  298.                        New_Item.Data (Rlen - (Max_Length - 1) .. Rlen);
  299.  
  300.                   else
  301.                      Source.Data (1 .. Max_Length - Rlen) :=
  302.                        Source.Data (Llen - (Max_Length - Rlen + 1) .. Llen);
  303.                      Source.Data (Max_Length - Rlen + 1 .. Max_Length) :=
  304.                        New_Item.Data;
  305.                   end if;
  306.  
  307.                when Strings.Error =>
  308.                   raise Strings.Length_Error;
  309.             end case;
  310.          end if;
  311.  
  312.       end Append;
  313.  
  314.       --  Case of Bounded_String and String
  315.  
  316.       function Append
  317.         (Left  : in Bounded_String;
  318.          Right : in String;
  319.          Drop  : in Strings.Truncation := Strings.Error)
  320.          return  Bounded_String
  321.       is
  322.          Result : Bounded_String;
  323.          Llen   : constant Length_Range := Left.Length;
  324.          Rlen   : constant Length_Range := Right'Length;
  325.  
  326.       begin
  327.          if Llen + Rlen <= Max_Length then
  328.             Result.Length := Llen + Rlen;
  329.             Result.Data (1 .. Llen) := Left.Data;
  330.             Result.Data (Llen + 1 .. Llen + Rlen) := Right;
  331.  
  332.          else
  333.             Result.Length := Max_Length;
  334.  
  335.             case Drop is
  336.                when Strings.Right =>
  337.                   if Llen >= Max_Length then
  338.                      Result.Data (1 .. Max_Length) :=
  339.                        Left.Data (1 .. Max_Length);
  340.  
  341.                   else
  342.                      Result.Data (1 .. Llen) := Left.Data;
  343.                      Result.Data (Llen + 1 .. Max_Length) :=
  344.                        Right (1 .. Max_Length - Llen);
  345.                   end if;
  346.  
  347.                when Strings.Left =>
  348.                   if Rlen >= Max_Length then
  349.                      Result.Data (1 .. Max_Length) :=
  350.                        Right (Rlen - (Max_Length - 1) .. Rlen);
  351.  
  352.                   else
  353.                      Result.Data (1 .. Max_Length - Rlen) :=
  354.                        Left.Data (Llen - (Max_Length - Rlen + 1) .. Llen);
  355.                      Result.Data (Max_Length - Rlen + 1 .. Max_Length) :=
  356.                        Right;
  357.                   end if;
  358.  
  359.                when Strings.Error =>
  360.                   raise Strings.Length_Error;
  361.             end case;
  362.          end if;
  363.  
  364.          return Result;
  365.       end Append;
  366.  
  367.       procedure Append
  368.         (Source   : in out Bounded_String;
  369.          New_Item : in String;
  370.          Drop     : in Truncation  := Error)
  371.       is
  372.          Llen   : constant Length_Range := Source.Length;
  373.          Rlen   : constant Length_Range := New_Item'Length;
  374.  
  375.       begin
  376.          if Llen + Rlen <= Max_Length then
  377.             Source.Length := Llen + Rlen;
  378.             Source.Data (Llen + 1 .. Llen + Rlen) := New_Item;
  379.  
  380.          else
  381.             Source.Length := Max_Length;
  382.  
  383.             case Drop is
  384.                when Strings.Right =>
  385.                   if Llen < Max_Length then
  386.                      Source.Data (Llen + 1 .. Max_Length) :=
  387.                        New_Item (1 .. Max_Length - Llen);
  388.                   end if;
  389.  
  390.                when Strings.Left =>
  391.                   if Rlen >= Max_Length then
  392.                      Source.Data (1 .. Max_Length) :=
  393.                        New_Item (Rlen - (Max_Length - 1) .. Rlen);
  394.  
  395.                   else
  396.                      Source.Data (1 .. Max_Length - Rlen) :=
  397.                        Source.Data (Llen - (Max_Length - Rlen + 1) .. Llen);
  398.                      Source.Data (Max_Length - Rlen + 1 .. Max_Length) :=
  399.                        New_Item;
  400.                   end if;
  401.  
  402.                when Strings.Error =>
  403.                   raise Strings.Length_Error;
  404.             end case;
  405.          end if;
  406.  
  407.       end Append;
  408.  
  409.       --  Case of String and Bounded_String
  410.  
  411.       function Append
  412.         (Left  : in String;
  413.          Right : in Bounded_String;
  414.          Drop  : in Strings.Truncation := Strings.Error)
  415.          return  Bounded_String
  416.       is
  417.          Result : Bounded_String;
  418.          Llen   : constant Length_Range := Left'Length;
  419.          Rlen   : constant Length_Range := Right.Length;
  420.  
  421.       begin
  422.          if Llen + Rlen <= Max_Length then
  423.             Result.Length := Llen + Rlen;
  424.             Result.Data (1 .. Llen) := Left;
  425.             Result.Data (Llen + 1 .. Llen + Rlen) := Right.Data;
  426.  
  427.          else
  428.             Result.Length := Max_Length;
  429.  
  430.             case Drop is
  431.                when Strings.Right =>
  432.                   if Llen >= Max_Length then
  433.                      Result.Data (1 .. Max_Length) := Left (1 .. Max_Length);
  434.  
  435.                   else
  436.                      Result.Data (1 .. Llen) := Left;
  437.                      Result.Data (Llen + 1 .. Max_Length) :=
  438.                        Right.Data (1 .. Max_Length - Llen);
  439.                   end if;
  440.  
  441.                when Strings.Left =>
  442.                   if Rlen >= Max_Length then
  443.                      Result.Data (1 .. Max_Length) :=
  444.                        Right.Data (Rlen - (Max_Length - 1) .. Rlen);
  445.  
  446.                   else
  447.                      Result.Data (1 .. Max_Length - Rlen) :=
  448.                        Left (Llen - (Max_Length - Rlen + 1) .. Llen);
  449.                      Result.Data (Max_Length - Rlen + 1 .. Max_Length) :=
  450.                        Right.Data;
  451.                   end if;
  452.  
  453.                when Strings.Error =>
  454.                   raise Strings.Length_Error;
  455.             end case;
  456.          end if;
  457.  
  458.          return Result;
  459.       end Append;
  460.  
  461.       --  Case of Bounded_String and Character
  462.  
  463.       function Append
  464.         (Left  : in Bounded_String;
  465.          Right : in Character;
  466.          Drop  : in Strings.Truncation := Strings.Error)
  467.          return  Bounded_String
  468.       is
  469.          Result : Bounded_String;
  470.          Llen   : constant Length_Range := Left.Length;
  471.  
  472.       begin
  473.          if Llen  < Max_Length then
  474.             Result.Length := Llen + 1;
  475.             Result.Data (1 .. Llen) := Left.Data (1 .. Llen);
  476.             Result.Data (Llen + 1) := Right;
  477.  
  478.          else
  479.             Result.Length := Max_Length;
  480.  
  481.             case Drop is
  482.                when Strings.Right =>
  483.                   Result.Data := Left.Data;
  484.  
  485.                when Strings.Left =>
  486.                   Result.Data (1 .. Max_Length - 1) :=
  487.                     Left.Data (2 .. Max_Length);
  488.                   Result.Data (Max_Length) := Right;
  489.  
  490.                when Strings.Error =>
  491.                   raise Strings.Length_Error;
  492.             end case;
  493.          end if;
  494.  
  495.          return Result;
  496.       end Append;
  497.  
  498.       procedure Append
  499.         (Source   : in out Bounded_String;
  500.          New_Item : in Character;
  501.          Drop     : in Truncation  := Error)
  502.       is
  503.          Llen   : constant Length_Range := Source.Length;
  504.  
  505.       begin
  506.          if Llen  < Max_Length then
  507.             Source.Length := Llen + 1;
  508.             Source.Data (Llen + 1) := New_Item;
  509.  
  510.          else
  511.             Source.Length := Max_Length;
  512.  
  513.             case Drop is
  514.                when Strings.Right =>
  515.                   null;
  516.  
  517.                when Strings.Left =>
  518.                   Source.Data (1 .. Max_Length - 1) :=
  519.                     Source.Data (2 .. Max_Length);
  520.                   Source.Data (Max_Length) := New_Item;
  521.  
  522.                when Strings.Error =>
  523.                   raise Strings.Length_Error;
  524.             end case;
  525.          end if;
  526.  
  527.       end Append;
  528.  
  529.       --  Case of Character and Bounded_String
  530.  
  531.       function Append
  532.         (Left  : in Character;
  533.          Right : in Bounded_String;
  534.          Drop  : in Strings.Truncation := Strings.Error)
  535.          return  Bounded_String
  536.       is
  537.          Result : Bounded_String;
  538.          Rlen   : constant Length_Range := Right.Length;
  539.  
  540.       begin
  541.          if Rlen < Max_Length then
  542.             Result.Length := Rlen + 1;
  543.             Result.Data (1) := Left;
  544.             Result.Data (2 .. Rlen + 1) := Right.Data (1 .. Rlen);
  545.  
  546.          else
  547.             Result.Length := Max_Length;
  548.  
  549.             case Drop is
  550.                when Strings.Right =>
  551.                   Result.Data (1) := Left;
  552.                   Result.Data (2 .. Max_Length) :=
  553.                     Right.Data (1 .. Max_Length - 1);
  554.  
  555.                when Strings.Left =>
  556.                   Result.Data (1 .. Max_Length) :=
  557.                     Right.Data (Rlen - (Max_Length - 1) .. Rlen);
  558.  
  559.                when Strings.Error =>
  560.                   raise Strings.Length_Error;
  561.             end case;
  562.          end if;
  563.  
  564.          return Result;
  565.       end Append;
  566.  
  567.       -----------
  568.       -- Count --
  569.       -----------
  570.  
  571.       function Count
  572.         (Source   : in Bounded_String;
  573.          Pattern  : in String;
  574.          Mapping  : in Maps.Character_Mapping := Maps.Identity)
  575.          return Natural
  576.       is
  577.       begin
  578.          return
  579.            Search.Count (Source.Data (1 .. Source.Length), Pattern, Mapping);
  580.       end Count;
  581.  
  582.       function Count
  583.         (Source   : in Bounded_String;
  584.          Pattern  : in String;
  585.          Mapping  : in Maps.Character_Mapping_Function)
  586.          return Natural
  587.       is
  588.       begin
  589.          return
  590.            Search.Count (Source.Data (1 .. Source.Length), Pattern, Mapping);
  591.       end Count;
  592.  
  593.       function Count
  594.         (Source : in Bounded_String;
  595.          Set    : in Maps.Character_Set)
  596.          return   Natural
  597.       is
  598.       begin
  599.          return Search.Count (Source.Data (1 .. Source.Length), Set);
  600.       end Count;
  601.  
  602.       ------------
  603.       -- Delete --
  604.       ------------
  605.  
  606.       function Delete
  607.         (Source  : in Bounded_String;
  608.          From    : in Positive;
  609.          Through : in Natural)
  610.          return    Bounded_String
  611.       is
  612.          Slen       : constant Natural := Source.Length;
  613.          Num_Delete : constant Integer := Through - From + 1;
  614.          Result     : Bounded_String;
  615.  
  616.       begin
  617.          if Num_Delete < 0 then
  618.             Result.Length := Slen;
  619.             Result.Data (1 .. Slen) := Source.Data (1 .. Slen);
  620.  
  621.          elsif From > Slen then
  622.             raise Strings.Index_Error;
  623.  
  624.          elsif Through >= Slen then
  625.             Result.Data (1 .. From - 1) := Source.Data (1 .. From - 1);
  626.             Result.Length := From - 1;
  627.  
  628.          else
  629.             Result.Data (1 .. From - 1) := Source.Data (1 .. From - 1);
  630.             Result.Length := Slen - Num_Delete;
  631.             Result.Data (From .. Result.Length) :=
  632.               Source.Data (Through + 1 .. Slen);
  633.          end if;
  634.  
  635.          return Result;
  636.       end Delete;
  637.  
  638.       procedure Delete
  639.         (Source  : in out Bounded_String;
  640.          From    : in Positive;
  641.          Through : in Natural)
  642.       is
  643.          Slen       : constant Natural := Source.Length;
  644.          Num_Delete : constant Integer := Through - From + 1;
  645.  
  646.       begin
  647.          if Num_Delete < 0 then
  648.             return;
  649.  
  650.          elsif From > Slen then
  651.             raise Strings.Index_Error;
  652.  
  653.          elsif Through >= Slen then
  654.             Source.Length := From - 1;
  655.  
  656.          else
  657.             Source.Length := Slen - Num_Delete;
  658.             Source.Data (From .. Source.Length) :=
  659.               Source.Data (Through + 1 .. Slen);
  660.          end if;
  661.       end Delete;
  662.  
  663.       -------------
  664.       -- Element --
  665.       -------------
  666.  
  667.       function Element
  668.         (Source : in Bounded_String;
  669.          Index  : in Positive)
  670.          return   Character
  671.       is
  672.       begin
  673.          if Index in 1 .. Source.Length then
  674.             return Source.Data (Index);
  675.          else
  676.             raise Strings.Index_Error;
  677.          end if;
  678.       end Element;
  679.  
  680.       ----------------
  681.       -- Find_Token --
  682.       ----------------
  683.  
  684.       procedure Find_Token
  685.         (Source : in Bounded_String;
  686.          Set    : in Maps.Character_Set;
  687.          Test   : in Strings.Membership;
  688.          First  : out Positive;
  689.          Last   : out Natural)
  690.       is
  691.       begin
  692.          Search.Find_Token
  693.            (Source.Data (1 .. Source.Length), Set, Test, First, Last);
  694.       end Find_Token;
  695.  
  696.       ----------
  697.       -- Head --
  698.       ----------
  699.  
  700.       function Head
  701.         (Source : in Bounded_String;
  702.          Count  : in Natural;
  703.          Pad    : in Character := Space;
  704.          Drop   : in Strings.Truncation := Strings.Error)
  705.          return   Bounded_String
  706.       is
  707.          Result : Bounded_String;
  708.          Slen   : constant Natural := Source.Length;
  709.          Npad   : constant Integer := Count - Slen;
  710.  
  711.       begin
  712.          if Npad <= 0 then
  713.             Result.Length := Count;
  714.             Result.Data (1 .. Count) := Source.Data (1 .. Count);
  715.  
  716.          elsif Count <= Max_Length then
  717.             Result.Length := Count;
  718.             Result.Data (1 .. Slen) := Source.Data (1 .. Slen);
  719.             Result.Data (Slen + 1 .. Count) := (others => Pad);
  720.  
  721.          else
  722.             Result.Length := Max_Length;
  723.  
  724.             case Drop is
  725.                when Strings.Right =>
  726.                   Result.Data (1 .. Slen) := Source.Data (1 .. Slen);
  727.                   Result.Data (Slen + 1 .. Max_Length) := (others => Pad);
  728.  
  729.                when Strings.Left =>
  730.                   if Npad > Max_Length then
  731.                      Result.Data := (others => Pad);
  732.  
  733.                   else
  734.                      Result.Data (1 .. Max_Length - Npad) :=
  735.                        Source.Data (Count - Max_Length + 1 .. Slen);
  736.                      Result.Data (Max_Length - Npad + 1 .. Max_Length) :=
  737.                        (others => Pad);
  738.                   end if;
  739.  
  740.                when Strings.Error =>
  741.                   raise Strings.Length_Error;
  742.             end case;
  743.          end if;
  744.  
  745.          return Result;
  746.       end Head;
  747.  
  748.       procedure Head
  749.         (Source : in out Bounded_String;
  750.          Count  : in Natural;
  751.          Pad    : in Character  := Space;
  752.          Drop   : in Truncation := Error)
  753.       is
  754.          Slen   : constant Natural := Source.Length;
  755.          Npad   : constant Integer := Count - Slen;
  756.          Temp   : Bounded_String;
  757.  
  758.       begin
  759.          Temp.Length := Slen;
  760.          Temp.Data (1 .. Slen) := Source.Data (1 .. Slen);
  761.          if Npad <= 0 then
  762.             Source.Length := Count;
  763.  
  764.          elsif Count <= Max_Length then
  765.             Source.Length := Count;
  766.             Source.Data (Slen + 1 .. Count) := (others => Pad);
  767.  
  768.          else
  769.             Source.Length := Max_Length;
  770.  
  771.             case Drop is
  772.                when Strings.Right =>
  773.                   Source.Data (Slen + 1 .. Max_Length) := (others => Pad);
  774.  
  775.                when Strings.Left =>
  776.                   if Npad > Max_Length then
  777.                      Source.Data := (others => Pad);
  778.  
  779.                   else
  780.                      Source.Data (1 .. Max_Length - Npad) :=
  781.                        Temp.Data (Count - Max_Length + 1 .. Slen);
  782.                      Source.Data (Max_Length - Npad + 1 .. Max_Length) :=
  783.                        (others => Pad);
  784.                   end if;
  785.  
  786.                when Strings.Error =>
  787.                   raise Strings.Length_Error;
  788.             end case;
  789.          end if;
  790.  
  791.       end Head;
  792.  
  793.       -----------
  794.       -- Index --
  795.       -----------
  796.  
  797.       function Index
  798.         (Source   : in Bounded_String;
  799.          Pattern  : in String;
  800.          Going    : in Strings.Direction := Strings.Forward;
  801.          Mapping  : in Maps.Character_Mapping := Maps.Identity)
  802.          return     Natural
  803.       is
  804.       begin
  805.          return Search.Index
  806.            (Source.Data (1 .. Source.Length), Pattern, Going, Mapping);
  807.       end Index;
  808.  
  809.       function Index
  810.         (Source   : in Bounded_String;
  811.          Pattern  : in String;
  812.          Going    : in Direction := Forward;
  813.          Mapping  : in Maps.Character_Mapping_Function)
  814.          return Natural
  815.       is
  816.       begin
  817.          return Search.Index
  818.            (Source.Data (1 .. Source.Length), Pattern, Going, Mapping);
  819.       end Index;
  820.  
  821.       function Index
  822.         (Source : in Bounded_String;
  823.          Set    : in Maps.Character_Set;
  824.          Test   : in Strings.Membership := Strings.Inside;
  825.          Going  : in Strings.Direction  := Strings.Forward)
  826.          return   Natural
  827.       is
  828.       begin
  829.          return Search.Index
  830.            (Source.Data (1 .. Source.Length), Set, Test, Going);
  831.       end Index;
  832.  
  833.       ---------------------
  834.       -- Index_Non_Blank --
  835.       ---------------------
  836.  
  837.       function Index_Non_Blank
  838.         (Source : in Bounded_String;
  839.          Going  : in Strings.Direction := Strings.Forward)
  840.          return   Natural
  841.       is
  842.       begin
  843.          return
  844.            Search.Index_Non_Blank (Source.Data (1 .. Source.Length), Going);
  845.       end Index_Non_Blank;
  846.  
  847.       ------------
  848.       -- Insert --
  849.       ------------
  850.  
  851.       function Insert
  852.         (Source   : in Bounded_String;
  853.          Before   : in Positive;
  854.          New_Item : in String;
  855.          Drop     : in Strings.Truncation := Strings.Error)
  856.          return     Bounded_String
  857.       is
  858.          Slen    : constant Natural := Source.Length;
  859.          Nlen    : constant Natural := New_Item'Length;
  860.          Tlen    : constant Natural := Slen + Nlen;
  861.          Blen    : constant Natural := Before - 1;
  862.          Alen    : constant Integer := Slen - Blen;
  863.          Droplen : constant Integer := Tlen - Max_Length;
  864.          Result  : Bounded_String;
  865.  
  866.          --  Tlen is the length of the total string before possible truncation.
  867.          --  Blen, Alen are the lengths of the before and after pieces of the
  868.          --  source string.
  869.  
  870.       begin
  871.          if Alen < 0 then
  872.             raise Index_Error;
  873.  
  874.          elsif Droplen <= 0 then
  875.             Result.Length := Tlen;
  876.             Result.Data (1 .. Blen) := Source.Data (1 .. Blen);
  877.             Result.Data (Before .. Before + Nlen - 1) := New_Item;
  878.             Result.Data (Before + Nlen .. Tlen) :=
  879.               Source.Data (Before .. Slen);
  880.  
  881.          else
  882.             Result.Length := Max_Length;
  883.  
  884.             case Drop is
  885.                when Strings.Right =>
  886.                   Result.Data (1 .. Blen) := Source.Data (1 .. Blen);
  887.  
  888.                   if Droplen > Alen then
  889.                      Result.Data (Before .. Max_Length) :=
  890.                        New_Item (New_Item'First
  891.                                    .. New_Item'First + Max_Length - Before);
  892.                   else
  893.                      Result.Data (Before .. Before + Nlen - 1) := New_Item;
  894.                      Result.Data (Before + Nlen .. Max_Length) :=
  895.                        Source.Data (Before .. Slen - Droplen);
  896.                   end if;
  897.  
  898.                when Strings.Left =>
  899.                   Result.Data (Max_Length - (Alen - 1) .. Max_Length) :=
  900.                     Source.Data (Before .. Slen);
  901.  
  902.                   if Droplen >= Blen then
  903.                      Result.Data (1 .. Max_Length - Alen) :=
  904.                        New_Item (New_Item'Last - (Max_Length - Alen) + 1
  905.                                    .. New_Item'Last);
  906.                   else
  907.                      Result.Data
  908.                        (Blen - Droplen + 1 .. Max_Length - Alen) :=
  909.                          New_Item;
  910.                      Result.Data (1 .. Blen - Droplen) :=
  911.                        Source.Data (Droplen + 1 .. Blen);
  912.                   end if;
  913.  
  914.                when Strings.Error =>
  915.                   raise Strings.Length_Error;
  916.             end case;
  917.          end if;
  918.  
  919.          return Result;
  920.       end Insert;
  921.  
  922.       procedure Insert
  923.         (Source   : in out Bounded_String;
  924.          Before   : in Positive;
  925.          New_Item : in String;
  926.          Drop     : in Strings.Truncation := Strings.Error)
  927.       is
  928.       begin
  929.          --  We do a double copy here because this is one of the situations
  930.          --  in which we move data to the right, and at least at the moment,
  931.          --  GNAT is not handling such cases correctly ???
  932.  
  933.          Source := Insert (Source, Before, New_Item, Drop);
  934.       end Insert;
  935.  
  936.       ------------
  937.       -- Length --
  938.       ------------
  939.  
  940.       function Length (Source : in Bounded_String) return Length_Range is
  941.       begin
  942.          return Source.Length;
  943.       end Length;
  944.  
  945.       ---------------
  946.       -- Overwrite --
  947.       ---------------
  948.  
  949.       function Overwrite
  950.         (Source    : in Bounded_String;
  951.          Position  : in Positive;
  952.          New_Item  : in String;
  953.          Drop      : in Strings.Truncation := Strings.Error)
  954.          return      Bounded_String
  955.       is
  956.          Result  : Bounded_String;
  957.          Endpos  : constant Positive := Position + New_Item'Length - 1;
  958.          Slen    : constant Natural  := Source.Length;
  959.          Droplen : Natural;
  960.  
  961.       begin
  962.          if Endpos <= Slen then
  963.             Result.Data (1 .. Position - 1) := Source.Data (1 .. Position - 1);
  964.             Result.Data (Position .. Endpos) := New_Item;
  965.             Result.Length := Source.Length;
  966.  
  967.          elsif Endpos <= Max_Length then
  968.             Result.Data (1 .. Position - 1) := Source.Data (1 .. Position - 1);
  969.             Result.Data (Position .. Endpos) := New_Item;
  970.             Result.Length := Endpos;
  971.  
  972.          else
  973.             Result.Length := Max_Length;
  974.             Droplen := Endpos - Max_Length;
  975.  
  976.             case Drop is
  977.                when Strings.Right =>
  978.                   Result.Data (1 .. Position - 1) :=
  979.                     Source.Data (1 .. Position - 1);
  980.                   Result.Data (Position .. Max_Length) :=
  981.                     New_Item (New_Item'First .. New_Item'Last - Droplen);
  982.  
  983.                when Strings.Left =>
  984.                   if New_Item'Length > Max_Length then
  985.                      Result.Data (1 .. Max_Length) :=
  986.                         New_Item (New_Item'Last - Max_Length + 1 ..
  987.                                   New_Item'Last);
  988.  
  989.                   else
  990.                      Result.Data (1 .. Max_Length - New_Item'Length) :=
  991.                        Source.Data (Droplen + 1 .. Position - 1);
  992.                      Result.Data
  993.                        (Max_Length - New_Item'Length + 1 .. Max_Length) :=
  994.                          New_Item;
  995.                   end if;
  996.  
  997.                when Strings.Error =>
  998.                   raise Strings.Length_Error;
  999.             end case;
  1000.          end if;
  1001.  
  1002.          return Result;
  1003.       end Overwrite;
  1004.  
  1005.       procedure Overwrite
  1006.         (Source    : in out Bounded_String;
  1007.          Position  : in Positive;
  1008.          New_Item  : in String;
  1009.          Drop      : in Strings.Truncation := Strings.Error)
  1010.       is
  1011.          Endpos  : constant Positive := Position + New_Item'Length - 1;
  1012.          Slen    : constant Natural  := Source.Length;
  1013.          Droplen : Natural;
  1014.  
  1015.       begin
  1016.          if Endpos <= Slen then
  1017.             Source.Data (Position .. Endpos) := New_Item;
  1018.  
  1019.          elsif Endpos <= Max_Length then
  1020.             Source.Data (Position .. Endpos) := New_Item;
  1021.             Source.Length := Endpos;
  1022.  
  1023.          else
  1024.             Source.Length := Max_Length;
  1025.             Droplen := Endpos - Max_Length;
  1026.  
  1027.             case Drop is
  1028.                when Strings.Right =>
  1029.                   Source.Data (Position .. Max_Length) :=
  1030.                     New_Item (New_Item'First .. New_Item'Last - Droplen);
  1031.  
  1032.                when Strings.Left =>
  1033.                   if New_Item'Length > Max_Length then
  1034.                      Source.Data (1 .. Max_Length) :=
  1035.                         New_Item (New_Item'Last - Max_Length + 1 ..
  1036.                                   New_Item'Last);
  1037.  
  1038.                   else
  1039.                      Source.Data (1 .. Max_Length - New_Item'Length) :=
  1040.                        Source.Data (Droplen + 1 .. Position - 1);
  1041.                      Source.Data
  1042.                        (Max_Length - New_Item'Length + 1 .. Max_Length) :=
  1043.                          New_Item;
  1044.                   end if;
  1045.  
  1046.                when Strings.Error =>
  1047.                   raise Strings.Length_Error;
  1048.             end case;
  1049.          end if;
  1050.       end Overwrite;
  1051.  
  1052.       ---------------------
  1053.       -- Replace_Element --
  1054.       ---------------------
  1055.  
  1056.       procedure Replace_Element
  1057.         (Source : in out Bounded_String;
  1058.          Index  : in Positive;
  1059.          By     : in Character)
  1060.       is
  1061.       begin
  1062.          if Index <= Source.Length then
  1063.             Source.Data (Index) := By;
  1064.          else
  1065.             raise Strings.Index_Error;
  1066.          end if;
  1067.       end Replace_Element;
  1068.  
  1069.       -------------------
  1070.       -- Replace_Slice --
  1071.       -------------------
  1072.  
  1073.       function Replace_Slice
  1074.         (Source   : in Bounded_String;
  1075.          Low      : in Positive;
  1076.          High     : in Natural;
  1077.          By       : in String;
  1078.          Drop     : in Strings.Truncation := Strings.Error)
  1079.          return     Bounded_String
  1080.       is
  1081.          Slen : constant Natural := Source.Length;
  1082.  
  1083.       begin
  1084.          if Low > Slen + 1 then
  1085.             raise Strings.Index_Error;
  1086.  
  1087.          elsif High < Low then
  1088.             return Insert (Source, Low, By, Drop);
  1089.  
  1090.          else
  1091.             declare
  1092.                Blen    : constant Natural := Low - 1;
  1093.                Alen    : constant Natural := Slen - High;
  1094.                Tlen    : constant Natural := Blen + By'Length + Alen;
  1095.                Droplen : constant Integer := Tlen - Max_Length;
  1096.                Result  : Bounded_String;
  1097.  
  1098.                --  Tlen is the total length of the result string before any
  1099.                --  truncation. Blen and Alen are the lengths of the pieces
  1100.                --  of the original string that end up in the result string
  1101.                --  before and after the replaced slice.
  1102.  
  1103.             begin
  1104.                if Droplen <= 0 then
  1105.                   Result.Length := Tlen;
  1106.                   Result.Data (1 .. Blen) := Source.Data (1 .. Blen);
  1107.                   Result.Data (Low .. Low + By'Length - 1) := By;
  1108.                   Result.Data (Low + By'Length .. Tlen) :=
  1109.                     Source.Data (High + 1 .. Slen);
  1110.  
  1111.                else
  1112.                   Result.Length := Max_Length;
  1113.  
  1114.                   case Drop is
  1115.                      when Strings.Right =>
  1116.                         Result.Data (1 .. Blen) := Source.Data (1 .. Blen);
  1117.  
  1118.                         if Droplen > Alen then
  1119.                            Result.Data (Low .. Max_Length) :=
  1120.                              By (By'First .. By'First + Max_Length - Low);
  1121.                         else
  1122.                            Result.Data (Low .. Low + By'Length - 1) := By;
  1123.                            Result.Data (Low + By'Length .. Max_Length) :=
  1124.                              Source.Data (High + 1 .. Slen - Droplen);
  1125.                         end if;
  1126.  
  1127.                      when Strings.Left =>
  1128.                         Result.Data (Max_Length - (Alen - 1) .. Max_Length) :=
  1129.                           Source.Data (High + 1 .. Slen);
  1130.  
  1131.                         if Droplen >= Blen then
  1132.                            Result.Data (1 .. Max_Length - Alen) :=
  1133.                              By (By'Last - (Max_Length - Alen) + 1 .. By'Last);
  1134.                         else
  1135.                            Result.Data
  1136.                              (Blen - Droplen + 1 .. Max_Length - Alen) := By;
  1137.                            Result.Data (1 .. Blen - Droplen) :=
  1138.                              Source.Data (Droplen + 1 .. Blen);
  1139.                         end if;
  1140.  
  1141.                      when Strings.Error =>
  1142.                         raise Strings.Length_Error;
  1143.                   end case;
  1144.                end if;
  1145.  
  1146.                return Result;
  1147.             end;
  1148.          end if;
  1149.       end Replace_Slice;
  1150.  
  1151.       procedure Replace_Slice
  1152.         (Source   : in out Bounded_String;
  1153.          Low      : in Positive;
  1154.          High     : in Natural;
  1155.          By       : in String;
  1156.          Drop     : in Strings.Truncation := Strings.Error)
  1157.       is
  1158.       begin
  1159.          --  We do a double copy here because this is one of the situations
  1160.          --  in which we move data to the right, and at least at the moment,
  1161.          --  GNAT is not handling such cases correctly ???
  1162.  
  1163.          Source := Replace_Slice (Source, Low, High, By, Drop);
  1164.       end Replace_Slice;
  1165.  
  1166.       ---------------
  1167.       -- Replicate --
  1168.       ---------------
  1169.  
  1170.       function Replicate
  1171.         (Count : in Natural;
  1172.          Item  : in Character;
  1173.          Drop  : in Strings.Truncation := Strings.Error)
  1174.          return  Bounded_String
  1175.       is
  1176.          Result : Bounded_String;
  1177.  
  1178.       begin
  1179.          if Count <= Max_Length then
  1180.             Result.Length := Count;
  1181.  
  1182.          elsif Drop = Strings.Error then
  1183.             raise Strings.Length_Error;
  1184.  
  1185.          else
  1186.             Result.Length := Max_Length;
  1187.          end if;
  1188.  
  1189.          Result.Data (1 .. Result.Length) := (others => Item);
  1190.          return Result;
  1191.       end Replicate;
  1192.  
  1193.       function Replicate
  1194.         (Count : in Natural;
  1195.          Item  : in String;
  1196.          Drop  : in Strings.Truncation := Strings.Error)
  1197.          return  Bounded_String
  1198.       is
  1199.          Length : constant Integer := Count * Item'Length;
  1200.          Result : Bounded_String;
  1201.          Indx   : Positive;
  1202.  
  1203.       begin
  1204.          if Length <= Max_Length then
  1205.             Result.Length := Length;
  1206.             Indx := 1;
  1207.  
  1208.             for J in 1 .. Count loop
  1209.                Result.Data (Indx .. Indx + Item'Length - 1) := Item;
  1210.                Indx := Indx + Item'Length;
  1211.             end loop;
  1212.  
  1213.          else
  1214.             Result.Length := Max_Length;
  1215.  
  1216.             case Drop is
  1217.                when Strings.Right =>
  1218.                   Indx := 1;
  1219.  
  1220.                   while Indx + Item'Length <= Max_Length + 1 loop
  1221.                      Result.Data (Indx .. Indx + Item'Length - 1) := Item;
  1222.                      Indx := Indx + Item'Length;
  1223.                   end loop;
  1224.  
  1225.                   Result.Data (Indx .. Max_Length) :=
  1226.                     Item (1 .. Max_Length - Indx + 1);
  1227.  
  1228.                when Strings.Left =>
  1229.                   Indx := Max_Length;
  1230.  
  1231.                   while Indx - Item'Length >= 1 loop
  1232.                      Result.Data (Indx - (Item'Length - 1) .. Indx) := Item;
  1233.                      Indx := Indx - Item'Length;
  1234.                   end loop;
  1235.  
  1236.                   Result.Data (1 .. Indx) :=
  1237.                     Item (Item'Last - Indx + 1 .. Item'Last);
  1238.  
  1239.                when Strings.Error =>
  1240.                   raise Strings.Length_Error;
  1241.             end case;
  1242.          end if;
  1243.  
  1244.          return Result;
  1245.       end Replicate;
  1246.  
  1247.       function Replicate
  1248.         (Count : in Natural;
  1249.          Item  : in Bounded_String;
  1250.          Drop  : in Strings.Truncation := Strings.Error)
  1251.          return  Bounded_String
  1252.       is
  1253.       begin
  1254.          return Replicate (Count, Item.Data (1 .. Item.Length), Drop);
  1255.       end Replicate;
  1256.  
  1257.       -----------
  1258.       -- Slice --
  1259.       -----------
  1260.  
  1261.       function Slice
  1262.         (Source : in Bounded_String;
  1263.          Low    : in Positive;
  1264.          High   : in Natural)
  1265.          return   String is
  1266.       begin
  1267.          return Source.Data (Low .. High);
  1268.  
  1269.       exception
  1270.          when Constraint_Error =>
  1271.             raise Strings.Index_Error;
  1272.       end Slice;
  1273.  
  1274.       ----------
  1275.       -- Tail --
  1276.       ----------
  1277.  
  1278.       function Tail
  1279.         (Source : in Bounded_String;
  1280.          Count  : in Natural;
  1281.          Pad    : in Character := Space;
  1282.          Drop   : in Strings.Truncation := Strings.Error)
  1283.          return   Bounded_String
  1284.       is
  1285.          Result : Bounded_String;
  1286.          Slen   : constant Natural := Source.Length;
  1287.          Npad   : constant Integer := Count - Slen;
  1288.  
  1289.       begin
  1290.          if Npad <= 0 then
  1291.             Result.Length := Count;
  1292.             Result.Data (1 .. Count) :=
  1293.               Source.Data (Slen - (Count - 1) .. Slen);
  1294.  
  1295.          elsif Count <= Max_Length then
  1296.             Result.Length := Count;
  1297.             Result.Data (1 .. Npad) := (others => Pad);
  1298.             Result.Data (Npad + 1 .. Count) := Source.Data (1 .. Slen);
  1299.  
  1300.          else
  1301.             Result.Length := Max_Length;
  1302.  
  1303.             case Drop is
  1304.                when Strings.Right =>
  1305.                   if Npad > Max_Length then
  1306.                      Result.Data := (others => Pad);
  1307.  
  1308.                   else
  1309.                      Result.Data (1 .. Npad) := (others => Pad);
  1310.                      Result.Data (Npad + 1 .. Max_Length) :=
  1311.                        Source.Data (1 .. Max_Length - Npad);
  1312.                   end if;
  1313.  
  1314.                when Strings.Left =>
  1315.                   Result.Data (1 .. Max_Length - Slen) := (others => Pad);
  1316.                   Result.Data (Max_Length - Slen + 1 .. Max_Length) :=
  1317.                     Source.Data (1 .. Slen);
  1318.  
  1319.                when Strings.Error =>
  1320.                   raise Strings.Length_Error;
  1321.             end case;
  1322.          end if;
  1323.  
  1324.          return Result;
  1325.       end Tail;
  1326.  
  1327.       procedure Tail
  1328.         (Source : in out Bounded_String;
  1329.          Count  : in Natural;
  1330.          Pad    : in Character  := Space;
  1331.          Drop   : in Truncation := Error)
  1332.       is
  1333.          Slen   : constant Natural := Source.Length;
  1334.          Npad   : constant Integer := Count - Slen;
  1335.          Temp   : Bounded_String;
  1336.  
  1337.       begin
  1338.          Temp.Length := Slen;
  1339.          Temp.Data (1 .. Slen) := Source.Data (1 .. Slen);
  1340.          if Npad <= 0 then
  1341.             Source.Length := Count;
  1342.             Source.Data (1 .. Count) :=
  1343.               Temp.Data (Slen - (Count - 1) .. Slen);
  1344.  
  1345.          elsif Count <= Max_Length then
  1346.             Source.Length := Count;
  1347.             Source.Data (1 .. Npad) := (others => Pad);
  1348.             Source.Data (Npad + 1 .. Count) := Temp.Data (1 .. Slen);
  1349.  
  1350.          else
  1351.             Source.Length := Max_Length;
  1352.  
  1353.             case Drop is
  1354.                when Strings.Right =>
  1355.                   if Npad > Max_Length then
  1356.                      Source.Data := (others => Pad);
  1357.  
  1358.                   else
  1359.                      Source.Data (1 .. Npad) := (others => Pad);
  1360.                      Source.Data (Npad + 1 .. Max_Length) :=
  1361.                        Temp.Data (1 .. Max_Length - Npad);
  1362.                   end if;
  1363.  
  1364.                when Strings.Left =>
  1365.                   Source.Data (1 .. Max_Length - Slen) := (others => Pad);
  1366.                   Source.Data (Max_Length - Slen + 1 .. Max_Length) :=
  1367.                     Temp.Data (1 .. Slen);
  1368.  
  1369.                when Strings.Error =>
  1370.                   raise Strings.Length_Error;
  1371.             end case;
  1372.          end if;
  1373.  
  1374.       end Tail;
  1375.  
  1376.       -----------------------
  1377.       -- To_Bounded_String --
  1378.       -----------------------
  1379.  
  1380.       function To_Bounded_String
  1381.         (Source : in String;
  1382.          Drop   : in Strings.Truncation := Strings.Error)
  1383.          return   Bounded_String
  1384.       is
  1385.          Slen   : constant Length_Range := Source'Length;
  1386.          Result : Bounded_String;
  1387.  
  1388.       begin
  1389.          if Slen <= Max_Length then
  1390.             Result.Length := Slen;
  1391.             Result.Data (1 .. Slen) := Source;
  1392.  
  1393.          else
  1394.             case Drop is
  1395.                when Strings.Right =>
  1396.                   Result.Length := Max_Length;
  1397.                   Result.Data (1 .. Max_Length) := Source (1 .. Max_Length);
  1398.  
  1399.                when Strings.Left =>
  1400.                   Result.Length := Max_Length;
  1401.                   Result.Data (1 .. Max_Length) :=
  1402.                     Source (Slen - (Max_Length - 1) .. Slen);
  1403.  
  1404.                when Strings.Error =>
  1405.                   raise Strings.Length_Error;
  1406.             end case;
  1407.          end if;
  1408.  
  1409.          return Result;
  1410.       end To_Bounded_String;
  1411.  
  1412.       ---------------
  1413.       -- To_String --
  1414.       ---------------
  1415.  
  1416.       function To_String (Source : in Bounded_String) return String is
  1417.       begin
  1418.          return Source.Data (1 .. Source.Length);
  1419.       end To_String;
  1420.  
  1421.       ---------------
  1422.       -- Translate --
  1423.       ---------------
  1424.  
  1425.       function Translate
  1426.         (Source  : in Bounded_String;
  1427.          Mapping : in Maps.Character_Mapping)
  1428.          return    Bounded_String
  1429.       is
  1430.          Result : Bounded_String;
  1431.  
  1432.       begin
  1433.          Result.Length := Source.Length;
  1434.  
  1435.          for J in 1 .. Source.Length loop
  1436.             Result.Data (J) := Value (Mapping, Source.Data (J));
  1437.          end loop;
  1438.  
  1439.          return Result;
  1440.       end Translate;
  1441.  
  1442.       procedure Translate
  1443.         (Source : in out Bounded_String;
  1444.          Mapping  : in Maps.Character_Mapping)
  1445.       is
  1446.       begin
  1447.          for J in 1 .. Source.Length loop
  1448.             Source.Data (J) := Value (Mapping, Source.Data (J));
  1449.          end loop;
  1450.       end Translate;
  1451.  
  1452.       function Translate
  1453.         (Source  : in Bounded_String;
  1454.          Mapping : in Maps.Character_Mapping_Function)
  1455.          return Bounded_String
  1456.       is
  1457.          Result : Bounded_String;
  1458.  
  1459.       begin
  1460.          Result.Length := Source.Length;
  1461.  
  1462.          for J in 1 .. Source.Length loop
  1463.             Result.Data (J) := Mapping.all (Source.Data (J));
  1464.          end loop;
  1465.  
  1466.          return Result;
  1467.       end Translate;
  1468.  
  1469.       procedure Translate
  1470.         (Source  : in out Bounded_String;
  1471.          Mapping : in Maps.Character_Mapping_Function)
  1472.       is
  1473.       begin
  1474.          for J in 1 .. Source.Length loop
  1475.             Source.Data (J) := Mapping.all (Source.Data (J));
  1476.          end loop;
  1477.       end Translate;
  1478.  
  1479.       ----------
  1480.       -- Trim --
  1481.       ----------
  1482.  
  1483.       function Trim (Source : in Bounded_String; Side : in Trim_End)
  1484.          return Bounded_String
  1485.       is
  1486.          Result : Bounded_String;
  1487.          I      : Positive := Source.Length;
  1488.          J      : Positive := 1;
  1489.  
  1490.       begin
  1491.          if Side = Left or Side = Both then
  1492.             while Source.Data (J) = ' ' loop
  1493.                J := J + 1;
  1494.             end loop;
  1495.  
  1496.             Result.Length := I - J + 1;
  1497.             Result.Data (1 .. Result.Length) := Source.Data (J .. I);
  1498.             if Side = Left then
  1499.                return Result;
  1500.             end if;
  1501.          end if;
  1502.  
  1503.          if Side = Right or Side = Both then
  1504.             while Source.Data (I) = ' ' loop
  1505.                I := I - 1;
  1506.             end loop;
  1507.  
  1508.             Result.Length := I - J + 1;
  1509.             Result.Data (1 .. Result.Length) := Source.Data (J .. I);
  1510.             return Result;
  1511.          end if;
  1512.  
  1513.          Result.Length := 0;
  1514.          return Result;
  1515.       end Trim;
  1516.  
  1517.       procedure Trim
  1518.         (Source : in out Bounded_String;
  1519.          Side   : in Trim_End)
  1520.       is
  1521.          I      : Positive := Source.Length;
  1522.          J      : Positive := 1;
  1523.          Temp   : Bounded_String;
  1524.  
  1525.       begin
  1526.          Temp.Length := I;
  1527.          Temp.Data (1 .. I) := Source.Data (1 .. I);
  1528.          if Side = Left or Side = Both then
  1529.             while Temp.Data (J) = ' ' loop
  1530.                J := J + 1;
  1531.             end loop;
  1532.  
  1533.             Source.Length := I - J + 1;
  1534.             Source.Data (1 .. Source.Length) := Temp.Data (J .. I);
  1535.          end if;
  1536.  
  1537.          if Side = Right or Side = Both then
  1538.             while Temp.Data (I) = ' ' loop
  1539.                I := I - 1;
  1540.             end loop;
  1541.  
  1542.             Source.Length := I - J + 1;
  1543.             Source.Data (1 .. Source.Length) := Temp.Data (J .. I);
  1544.          end if;
  1545.  
  1546.       end Trim;
  1547.  
  1548.       function Trim
  1549.         (Source : in Bounded_String;
  1550.          Left   : in Maps.Character_Set;
  1551.          Right  : in Maps.Character_Set)
  1552.          return   Bounded_String
  1553.       is
  1554.          Result : Bounded_String;
  1555.  
  1556.       begin
  1557.          for J in 1 .. Source.Length loop
  1558.             if not Is_In (Source.Data (J), Left) then
  1559.                for K in reverse J .. Source.Length loop
  1560.                   if not Is_In (Source.Data (K), Right) then
  1561.                      Result.Length := K - K + 1;
  1562.                      Result.Data (1 .. Result.Length) := Source.Data (J .. K)
  1563. ;
  1564.                      return Result;
  1565.                   end if;
  1566.                end loop;
  1567.             end if;
  1568.          end loop;
  1569.  
  1570.          Result.Length := 0;
  1571.          return Result;
  1572.       end Trim;
  1573.  
  1574.       procedure Trim
  1575.         (Source : in out Bounded_String;
  1576.          Left   : in Maps.Character_Set;
  1577.          Right  : in Maps.Character_Set)
  1578.       is
  1579.       begin
  1580.          for J in 1 .. Source.Length loop
  1581.             if not Is_In (Source.Data (J), Left) then
  1582.                for K in reverse J .. Source.Length loop
  1583.                   if not Is_In (Source.Data (K), Right) then
  1584.                      if J = 1 then
  1585.                         Source.Length := K;
  1586.                         return;
  1587.                      else
  1588.                         Source.Length := K - J + 1;
  1589.                         Source.Data (1 .. Source.Length) :=
  1590.                           Source.Data (J .. K);
  1591.                         return;
  1592.                      end if;
  1593.                   end if;
  1594.                end loop;
  1595.             end if;
  1596.          end loop;
  1597.  
  1598.          Source.Length := 0;
  1599.       end Trim;
  1600.  
  1601.    end Generic_Bounded_Length;
  1602.  
  1603. end Ada.Strings.Bounded;
  1604.